package cn.liumouren.tool.pac.util;

import cn.liumouren.tool.pac.entity.Update;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;

import java.util.List;
import java.util.Map;

/**
 * @author Daniel Liu
 * @date 2021/3/4 01:27
 */
public class UpdateUtil {
    public static <T> void processWhere(UpdateWrapper<T> updateWrapper, Update update) {
        // 处理 eq
        processEq(updateWrapper, update);

        // 处理 like
        processLike(updateWrapper, update);

        // 处理 比较关系
        processCompare(updateWrapper, update);

        // 处理 in
        processIn(updateWrapper, update);
    }

    private static <T> void processIn(UpdateWrapper<T> updateWrapper, Update update) {
        if (update.getWhere() != null && !CollectionUtils.isEmpty(update.getWhere().getIn())) {
            Map<String, List<?>> in = update.getWhere().getIn();
            for (Map.Entry<String, List<?>> entry : in.entrySet()) {
                updateWrapper.in(entry.getKey(), entry.getValue());
            }
        }
    }

    private static <T> void processCompare(UpdateWrapper<T> updateWrapper, Update update) {
        processGt(updateWrapper, update);
        processGe(updateWrapper, update);
        processLt(updateWrapper, update);
        processLe(updateWrapper, update);
    }

    private static <T> void processLe(UpdateWrapper<T> updateWrapper, Update update) {
        if (update.getWhere() != null && !CollectionUtils.isEmpty(update.getWhere().getLe())) {
            Map<String, Number> le = update.getWhere().getLe();
            for (Map.Entry<String, Number> entry : le.entrySet()) {
                updateWrapper.le(entry.getKey(), entry.getValue());
            }
        }
    }

    private static <T> void processLt(UpdateWrapper<T> updateWrapper, Update update) {
        if (update.getWhere() != null && !CollectionUtils.isEmpty(update.getWhere().getLt())) {
            Map<String, Number> lt = update.getWhere().getLt();
            for (Map.Entry<String, Number> entry : lt.entrySet()) {
                updateWrapper.lt(entry.getKey(), entry.getValue());
            }
        }
    }

    private static <T> void processGe(UpdateWrapper<T> updateWrapper, Update update) {
        if (update.getWhere() != null && !CollectionUtils.isEmpty(update.getWhere().getGe())) {
            Map<String, Number> ge = update.getWhere().getGe();
            for (Map.Entry<String, Number> entry : ge.entrySet()) {
                updateWrapper.ge(entry.getKey(), entry.getValue());
            }
        }
    }

    private static <T> void processGt(UpdateWrapper<T> updateWrapper, Update update) {
        if (update.getWhere() != null && !CollectionUtils.isEmpty(update.getWhere().getGt())) {
            Map<String, Number> gt = update.getWhere().getGt();
            for (Map.Entry<String, Number> entry : gt.entrySet()) {
                updateWrapper.gt(entry.getKey(), entry.getValue());
            }
        }
    }

    private static <T> void processLike(UpdateWrapper<T> updateWrapper, Update update) {
        if (update.getWhere() != null && !CollectionUtils.isEmpty(update.getWhere().getLike())) {
            Map<String, Object> like = update.getWhere().getLike();
            updateWrapper.and(w -> {
                String k;
                Object v;
                for (Map.Entry<String, Object> entry : like.entrySet()) {
                    k = entry.getKey();
                    v = entry.getValue();
                    // 可能是List
                    if (v instanceof List) {
                        List<?> list = (List<?>) v;
                        for (Object o : list) {
                            setLike(w, k, (String) o);
                        }
                    } else {
                        // 单个值
                        setLike(w, k, (String) v);
                    }
                }
            });
        }
    }

    private static <T> void setLike(UpdateWrapper<T> updateWrapper, String column, String likeStr) {
        boolean isStart = likeStr.startsWith("%");
        boolean isEnd = likeStr.endsWith("%");
        if (isStart && isEnd) {
            updateWrapper.like(column, likeStr.substring(1, likeStr.length() - 1)).or();
            return;
        }
        // 以%开头不以%结尾
        if (isStart) {
            updateWrapper.likeLeft(column, likeStr.substring(1)).or();
            return;
        }
        // 以%结尾不以%开头
        if (isEnd) {
            updateWrapper.likeRight(column, likeStr.substring(0, likeStr.length() - 1)).or();
        }
    }

    private static <T> void processEq(UpdateWrapper<T> updateWrapper, Update update) {
        if (update.getWhere() != null && !CollectionUtils.isEmpty(update.getWhere().getEq())) {
            Map<String, Object> eq = update.getWhere().getEq();
            String key;
            Object value;
            for (Map.Entry<String, Object> entry : eq.entrySet()) {
                key = entry.getKey();
                value = entry.getValue();
                // 可能是List
                if (value instanceof List) {
                    List<?> list = (List<?>) value;
                    for (Object o : list) {
                        updateWrapper.eq(key, o);
                    }
                } else {
                    // 单个值
                    updateWrapper.eq(key, value);
                }
            }
        }
    }

    public static <T> void processSet(UpdateWrapper<T> updateWrapper, Update update) {
        // 处理 update
        processUpdate(updateWrapper, update);

        // 处理 offset
        processOffset(updateWrapper, update);
    }

    private static <T> void processOffset(UpdateWrapper<T> updateWrapper, Update update) {
        if (update.getSet() != null && !CollectionUtils.isEmpty(update.getSet().getOffset())) {
            Map<String, Number> offset = update.getSet().getOffset();
            for (Map.Entry<String, Number> entry : offset.entrySet()) {
                updateWrapper.setSql(entry.getKey() + "=" + entry.getKey() + "+(" + entry.getValue() + ")");
            }
        }
    }

    private static <T> void processUpdate(UpdateWrapper<T> updateWrapper, Update update) {
        if (update.getSet() != null && !CollectionUtils.isEmpty(update.getSet().getUpdate())) {
            Map<String, Object> u = update.getSet().getUpdate();
            for (Map.Entry<String, Object> entry : u.entrySet()) {
                updateWrapper.set(entry.getKey(), entry.getValue());
            }
        }
    }
}
